;- Waffle's Doom WAD loader ; first, the header globals Structure WadInfo_T ;WADID is a 4byte string "IWAD" or "PWAD" WADID.S NumLumps.l InfoTable.l ;extra data added by norm ;Total maps is a count of how many maps are included in the WAD TotalMaps.l ;WADStyle tryies to determine if Doom/Hexen .... WAD WADStyle.l WADName.s EndStructure Global WADInfo.WadInfo_T Structure FileLump_T FilePos.l Size.l Name.s ;extra data added by norm ;MapFlag identifies the Name is a Map Name ;and lumps after this are for this map MapFlag.l ;set flat=1 for a wall/floor/ceiling texture ;set flat=2 for a sprite image Flat.l Graphic.l ;extra data for tracking sprites and patches width.l height.l leftoff.l topoff.l column.l[8] ;and another extra to point to data (to skip the header) DataOff.l ;extra data to help match Sprite to DoomED ;SpriteIX is the index to this sprite ;This gets counted for each "New" sprite and not ;for the alternate animation frames. This is by counting ;the first 4 chars of name. If new, This gets indexed, else -1 SpriteIX.l ;DoomED is the Editor ID for the Thing that uses this Sprite DoomED.l EndStructure Global NewList WADDir.FileLump_T() Structure MapList_T Name.s LumpCount.l FilePos.l EndStructure Global NewList MapList.MapList_T() ;- Thing Struct Structure Thing_T ;doom and strife structure x.l y.l angle.l DoomED.l Flags.l ;Flagsbit hex description ;0 0x0001 Thing is on skill levels 1 & 2 ;1 0x0002 Thing is on skill level 3 ;2 0x0004 Thing is on skill levels 4 & 5 ;3 0x0008 Thing is deaf ;4 0x0010 Thing is Not in single player ;Boom adds the flags: ;5 0x0020 Thing is Not in deathmatch ;6 0x0040 Thing is Not in coop ;7 0x0080 Friendly monster ;hexen structure H.l ThingID.l Action.l Arg1.l Arg2.l Arg3.l Arg4.l Arg5.l ;Flagsbit hex description for Hexen ;0 0x0001 Thing is on skill levels 1 & 2 ;1 0x0002 Thing is on skill level 3 ;2 0x0004 Thing is on skill levels 4 & 5 ;3 0x0008 Thing is deaf ;4 0x0010 Thing is dormant - it will Not wake up Until it is activated using Thing_Activate ;5 0x0020 Thing appears only To the Fighter class ;6 0x0040 Thing appears only To the Cleric class ;7 0x0080 Thing appears only To the Mage class ;8 0x0100 Thing appears only in single-player games ;9 0x0200 Thing appears only in cooperative games ;10 0x0400 Thing appears only in deathmatch games ;Strife Flagsbit hex description ;0 0x0001 Thing is on skill levels 1 & 2 ;1 0x0002 Thing is on skill level 3 ;2 0x0004 Thing is on skill levels 4 & 5 ;3 0x0008 Thing stands still (only useful For specific enemies) ;4 0x0010 Thing will Not appear in single player ;5 0x0020 Thing is deaf ;6 0x0040 Thing is a friendly monster ;8 0x0100 Thing is 25% translucent ;9 0x0200 Thing is invisible ;extra for speed Graphic.l EndStructure ;- DoomED vs Sprite Name vs Lump Structure DoomSprite_T DoomED.l Name.s Graphic.l EndStructure Global NewList DoomSprite.DoomSprite_T() Macro AddDoom(ED,N) AddElement(DoomSprite()) DoomSprite()\DoomED=ED DoomSprite()\Name=N EndMacro ;we just do shareware doom AddDoom(3004 ,"POSS") AddDoom(9 ,"SPOS") AddDoom(3001 ,"TROO") addDoom(3002 ,"SARG") AddDoom(3003 ,"BOSS") AddDoom(2035 ,"BAR1") AddDoom(2018 ,"ARM1") AddDoom(2019 ,"ARM2") AddDoom(2011 ,"STIM") AddDoom(2012 ,"MEDI") AddDoom(2007 ,"CLIP") AddDoom(2048 ,"AMMO") AddDoom(2010 ,"ROCK") AddDoom(2046 ,"BROK") AddDoom(2008 ,"SHEL") AddDoom(8 ,"BPAK") AddDoom(2002 ,"MGUN") AddDoom(2005 ,"CSAW") AddDoom(2003 ,"LAUN") AddDoom(2004 ,"PLAS") AddDoom(2001 ,"SHOT") AddDoom(2028 ,"COLU") AddDoom(2014 ,"BON1") AddDoom(2015 ,"BON2") AddDoom(5 ,"BKEY") AddDoom(13 ,"RKEY") AddDoom(6 ,"YKEY") AddDoom(35 ,"CBRA") AddDoom(15 ,"PLAY") AddDoom(10 ,"PLAY") AddDoom(2049 ,"SBOX") ;1,2,3,4 are player start locations ;10,15 are player corpses ;11 is spawn points for Death Match Global NewList MapThing.Thing_T() ;- VertexStruct Structure Vertex_T VX.l VY.l EndStructure Global NewList Vertex.Vertex_T() ;- LineDef Struct Structure LineDef_T VStart.l VEnd.l Flags.l Special.l Sector.l RSideDef.l LSideDef.l ;extras for hexen Arg1.l Arg2.l Arg3.l Arg4.l Arg5.l ;actual vertex data PVStart.Vertex_T PVEnd.Vertex_T EndStructure Global NewList LineDef.LineDef_T() ;- SideDef Struct Structure SideDef_T xoffset.l yoffset.l ;texture names UTName.s LTName.s MTname.s Sector.l EndStructure Global NewList SideDef.SideDef_T() ;- Sector Struct Structure Sector_T FloorH.l CeilingH.l FName.s CName.s Light.l LType.l Tag.l EndStructure Global NewList Sector.Sector_T() ;- WAD Textures Structure PName_T LumpName.s LumpCount.l FilePos.l Size.l Graphic.l EndStructure Global NewList PName.PName_T() Structure Texture_T LumpCount.l FilePos.l Name.s Width.l height.l PatchCount.l FirstPatch.l Graphic.l EndStructure Global NewList Texture.Texture_T() Structure Patch_T OriginX.l OriginY.l Index.l Graphic.l Width.l Height.l EndStructure Global NewList Patch.Patch_T() Global Dim PlayPal.l(255) Global TransparentPal.l Global GraphicCount.l ;- Window Constants ; Enumeration #Window_List #Window_Prog #Window_OverView EndEnumeration ;- Gadget Constants ; Enumeration #ListIcon_0 #Button_1 #Button_2 #Button_3 #Button_4 #Button_5 #Button_6 #Button_7 #ProgressBar #Image_0 EndEnumeration Enumeration #ViewMenu EndEnumeration Enumeration #Reset #Exit #Quit #ZoomIN #ZoomOut #ZoomLeft #ZoomRight #ZoomUP #ZoomDown #Draw_ID #Draw_Sprite #Draw_Off EndEnumeration Procedure Open_Window_List() If OpenWindow(#Window_List, 275, 143, 442, 300, "New window ( 0 )", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar ) If CreateGadgetList(WindowID(#Window_List)) ListIconGadget(#ListIcon_0, 0, 0, 340, 290, "Map Name", 100) AddGadgetColumn(#ListIcon_0, 1, "Lump Index", 50) AddGadgetColumn(#ListIcon_0,2,"Index",50) ButtonGadget(#Button_1, 350, 10, 80, 30, "OK") ButtonGadget(#Button_2, 350, 250, 80, 30, "Quit") ButtonGadget(#Button_3, 350, 50, 80, 30, "Load") ButtonGadget(#Button_4, 350, 90, 80, 30, "") ButtonGadget(#Button_5, 350, 130, 80, 30, "") ButtonGadget(#Button_6, 350, 170, 80, 30, "") ButtonGadget(#Button_7, 350, 210, 80, 30, "") ImageGadget(#Image_0, 440, 0, 190, 280, 0) EndIf EndIf EndProcedure Procedure.l GetImageFromFile(File.l,Pos.l,Size.l) If Size<1 ProcedureReturn 0 EndIf FileSeek(File,pos) *mem=AllocateMemory(size) ReadData(File,*mem,size) GraphicCount+1 ;this is eather a sprite or a patch ;so, this is an array of columns ;3 byte header for each col and one stop byte at the end of each ;assume image is square ;so we must determine the image size ;each byte is a pixel, we need the PlayPal() ;to determine color .... W.l=Sqr(Size) CreateImage(GraphicCount,W,W) StartDrawing(ImageOutput(GraphicCount)) Off.l=0 For y=0 To W-1 For x=0 To W-1 CP.l=PeekB(*mem+off)&$FF Plot(x,y,PlayPal(CP)) Off + 1 Next x Next y StopDrawing() ;ResizeImage(GraphicCount,190,190) FreeMemory(*mem) ProcedureReturn GraphicCount EndProcedure Procedure MapDetails() GraphicCount + 1 CreateImage(GraphicCount,190,190) Open_Window_List() FN$=WADDir()\Name If WADInfo\WADStyle SetWindowTitle(#Window_List,FN$+" [HEXEN]") Else SetWindowTitle(#Window_List,FN$+" [DOOM]") EndIf DMode.l=#Button_3 SetGadgetText(#Button_3,"Summary") SetGadgetText(#Button_4,"PNames") SetGadgetText(#Button_5,"Flats") SetGadgetText(#Button_6,"Sprites") SetGadgetText(#Button_7,"Textures") SetGadgetItemText(#ListIcon_0,-1,"Map Data",0) SetGadgetItemText(#ListIcon_0,-1,"Value",1) SetGadgetItemText(#ListIcon_0,-1,"",2) msg$="Map Name"+Chr(10)+FN$ AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Things"+Chr(10)+Str(CountList(MapThing())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Lines"+Chr(10)+Str(CountList(LineDef())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Sides"+Chr(10)+Str(CountList(SideDef())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Vertexes"+Chr(10)+Str(CountList(Vertex())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Sectors"+Chr(10)+Str(CountList(Sector())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="PNames"+Chr(10)+Str(CountList(PName())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Textures"+Chr(10)+Str(CountList(Texture())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Patches"+Chr(10)+Str(CountList(Patch())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Total Lumps"+Chr(10)+Str(CountList(WADDir())) AddGadgetItem(#ListIcon_0,-1,msg$) TFlats.l=0 TSprites.l=0 ResetList(WADDir()) While NextElement(WADDir()) If WADDir()\Flat=1 TFlats + 1 ElseIf WADDir()\Flat=2 TSprites + 1 EndIf Wend msg$="Flats"+Chr(10)+Str(TFlats) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Sprites"+Chr(10)+Str(TSprites) AddGadgetItem(#ListIcon_0,-1,msg$) specials.l=0 ResetList(LineDef()) While NextElement(LineDef()) If LineDef()\Flags&$20 specials + 1 EndIf Wend msg$="Secrets"+Chr(10)+Str(specials) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="" SetGadgetState(#Image_0,0) Repeat ; Start of the event loop Event = WaitWindowEvent() ; This line waits until an event is received from Windows WindowID = EventWindow() ; The Window where the event is generated, can be used in the gadget procedures GadgetID = EventGadget() ; Is it a gadget event? EventType = EventType() ; The event type ;You can place code here, and use the result as parameters for the procedures If Event = #PB_Event_Gadget If GadgetID = #ListIcon_0 If EventType()=#PB_EventType_LeftClick If DMode>#Button_3 If DMode<#Button_7 C.l=GetGadgetState(#ListIcon_0) If C>=0 LumpName.s=GetGadgetItemText(#ListIcon_0,C) ResetList(WADDir()) While NextElement(WADDir()) If WADDir()\Name=LumpName If WADDir()\Graphic ResizeImage(GraphicCount,ImageWidth(WADDir()\Graphic),ImageHeight(WADDir()\Graphic)) StartDrawing(ImageOutput(GraphicCount)) DrawImage(ImageID(WADDir()\Graphic),0,0) StopDrawing() ResizeImage(GraphicCount,190,190) SetGadgetState(#Image_0,ImageID(GraphicCount)) ResizeGadget(#Image_0,#PB_Ignore,#PB_Ignore,190,190) Else SetGadgetState(#Image_0,0) EndIf Break EndIf Wend EndIf Else ;textures C.l=GetGadgetState(#ListIcon_0) If C>=0 TextureName.s=GetGadgetItemText(#ListIcon_0,C) ResetList(Texture()) While NextElement(Texture()) If Texture()\Name=TextureName If Texture()\Graphic ResizeImage(GraphicCount,ImageWidth(Texture()\Graphic),ImageHeight(Texture()\Graphic)) StartDrawing(ImageOutput(GraphicCount)) DrawImage(ImageID(Texture()\Graphic),0,0) StopDrawing() ResizeImage(GraphicCount,190,190) SetGadgetState(#Image_0,ImageID(GraphicCount)) ResizeGadget(#Image_0,#PB_Ignore,#PB_Ignore,190,190) Else SetGadgetState(#Image_0,0) EndIf Break EndIf Wend EndIf EndIf EndIf EndIf ElseIf GadgetID = #Button_1 Break ElseIf GadgetID = #Button_2 End ElseIf GadgetID = #Button_3 DMode.l=#Button_3 SetGadgetState(#Image_0,0) ClearGadgetItemList(#ListIcon_0) SetGadgetItemText(#ListIcon_0,-1,"Map Data",0) SetGadgetItemText(#ListIcon_0,-1,"Value",1) SetGadgetItemText(#ListIcon_0,-1,"",2) msg$="Map Name"+Chr(10)+FN$ AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Things"+Chr(10)+Str(CountList(MapThing())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Lines"+Chr(10)+Str(CountList(LineDef())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Sides"+Chr(10)+Str(CountList(SideDef())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Vertexes"+Chr(10)+Str(CountList(Vertex())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Sectors"+Chr(10)+Str(CountList(Sector())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="PNames"+Chr(10)+Str(CountList(PName())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Textures"+Chr(10)+Str(CountList(Texture())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Patches"+Chr(10)+Str(CountList(Patch())) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Total Lumps"+Chr(10)+Str(CountList(WADDir())) AddGadgetItem(#ListIcon_0,-1,msg$) TFlats.l=0 TSprites.l=0 ResetList(WADDir()) While NextElement(WADDir()) If WADDir()\Flat=1 TFlats + 1 ElseIf WADDir()\Flat=2 TSprites + 1 EndIf Wend msg$="Flats"+Chr(10)+Str(TFlats) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="Sprites"+Chr(10)+Str(TSprites) AddGadgetItem(#ListIcon_0,-1,msg$) specials.l=0 ResetList(LineDef()) While NextElement(LineDef()) If LineDef()\Flags&$20 specials + 1 EndIf Wend msg$="Secrets"+Chr(10)+Str(specials) AddGadgetItem(#ListIcon_0,-1,msg$) msg$="" ElseIf GadgetID = #Button_4 DMode.l=#Button_4 SetGadgetState(#Image_0,0) ClearGadgetItemList(#ListIcon_0) SetGadgetItemText(#ListIcon_0,-1,"Patch Name",0) SetGadgetItemText(#ListIcon_0,-1,"Size",1) SetGadgetItemText(#ListIcon_0,-1,"",2) ResetList(PName()) While NextElement(PName()) msg$=PName()\LumpName+Chr(10)+Str(PName()\Size) AddGadgetItem(#ListIcon_0,-1,msg$) Wend ElseIf GadgetID = #Button_5 DMode.l=#Button_5 SetGadgetState(#Image_0,0) ClearGadgetItemList(#ListIcon_0) SetGadgetItemText(#ListIcon_0,-1,"Flat Name",0) SetGadgetItemText(#ListIcon_0,-1,"Size",1) SetGadgetItemText(#ListIcon_0,-1,"",2) ResetList(WADDir()) While NextElement(WADDir()) If WADDir()\Flat=1 msg$=WADDir()\Name+Chr(10)+Str(WADDir()\Size) AddGadgetItem(#ListIcon_0,-1,msg$) EndIf Wend ElseIf GadgetID = #Button_6 DMode.l=#Button_6 SetGadgetState(#Image_0,0) ClearGadgetItemList(#ListIcon_0) SetGadgetItemText(#ListIcon_0,-1,"Sprite Name",0) SetGadgetItemText(#ListIcon_0,-1,"Size",1) SetGadgetItemText(#ListIcon_0,-1,"Index",2) ResetList(WADDir()) While NextElement(WADDir()) If WADDir()\Flat=2 msg$=WADDir()\Name+Chr(10)+Str(WADDir()\Size) If WADDir()\SpriteIX>=0 msg$=msg$+Chr(10)+Str(WADDir()\SpriteIX) EndIf AddGadgetItem(#ListIcon_0,-1,msg$) EndIf Wend ElseIf GadgetID = #Button_7 DMode.l=#Button_7 SetGadgetState(#Image_0,0) ClearGadgetItemList(#ListIcon_0) SetGadgetItemText(#ListIcon_0,-1,"Texture",0) SetGadgetItemText(#ListIcon_0,-1,"Patches",1) ResetList(Texture()) While NextElement(Texture()) msg$=Texture()\Name+Chr(10)+Str(Texture()\PatchCount) AddGadgetItem(#ListIcon_0,-1,msg$) Wend EndIf EndIf Until Event = #PB_Event_CloseWindow ; End of the event loop CloseWindow(#Window_List) EndProcedure Procedure.l LoadWAD(fn$) ;this loads FN$ as a WAD file ;the return value will be ;0 - failure ;1 - "IWAD" file loaded ;2 - "PWAD" file loaded reply.l=0 File.l=ReadFile(#PB_Any,FN$) If File *Mem=AllocateMemory(12) ReadData(File,*Mem,12) WADInfo.WadInfo_T\WADID=PeekS(*Mem,4) WADInfo\NumLumps=PeekL(*Mem+4) WADInfo\InfoTable=PeekL(*Mem+8) WADInfo\TotalMaps=0 WADInfo\WADStyle=0 WADInfo\WADName=FN$ FreeMemory(*Mem) If GraphicCount For G=0 To GraphicCount If IsImage(G) FreeImage(G) EndIf Next G GraphicCount=0 EndIf ;clear all texture data ClearList(PNAme()) ClearList(Texture()) ClearList(Patch()) ResetList(DoomSprite()) While NextElement(DoomSprite()) DoomSprite()\Graphic=0 Wend If OpenWindow(#Window_Prog, 394, 175, 351, 30, "Loading "+GetFilePart(FN$), #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_WindowCentered ) If CreateGadgetList(WindowID(#Window_Prog)) ProgressBarGadget(#ProgressBar, 0, 0, 350, 30, 0, WADInfo\NumLumps) SetGadgetState(#ProgressBar,0) EndIf EndIf ;- create the file directory *Mem=AllocateMemory(16) ClearList( WADDir()) ClearList(MapList()) FMod.l=0 FlatFlag.l=0 For FLump=1 To WADInfo\NumLumps FileSeek(File,WADInfo\InfoTable+FMod) ReadData(File,*Mem,16) AddElement(WADDir()) WADDir()\FilePos=PeekL(*Mem) WADDir()\Size=PeekL(*Mem+4) WADdir()\Name=Trim(PeekS(*Mem+8,8)) WADDir()\Flat=FlatFlag If Left(WADDir()\Name,4)<>Last4.s Last4=Left(WADDir()\Name,4) If WADDir()\Flat=2 SpriteIX.l + 1 WADDir()\SpriteIX= SpriteIX Else WADDir()\SpriteIX= -1 EndIf Else WADDir()\SpriteIX= -1 EndIf If WADDir()\Name="THINGS" WADInfo\TotalMaps + 1 PreviousElement(WADDir()) WADDir()\MapFlag=1 AddElement(MapList()) MapList()\Name=WADDir()\Name MapList()\LumpCount=ListIndex(WADdir()) MapList()\FilePos=WADDir()\FilePos NextElement(WADDir()) ElseIf WADDir()\Name="BEHAVIOR" ;hexen style map WADInfo\WADStyle=1 ElseIf WADDir()\Name="PLAYPAL" ;256 color pallet *mem2=AllocateMemory(WADDir()\Size) FileSeek(File,WADDir()\FilePos) ReadData(File,*mem2,WADDir()\Size) POff.l=0 For Pal=0 To 255 B.l=PeekB(*mem2+POff)&$FF G.l=PeekB(*mem2+POff+1)&$FF R.l=PeekB(*mem2+POff+2)&$FF POff + 3 PlayPal(Pal)=R<<16|G<<8|B Next Pal FreeMemory(*mem2) TransparentPal = -1 For P1=0 To 254 For p2=p1+1 To 255 If PlayPal(p2)=PlayPal(p1) TransparentPal = p2 Break 2 EndIf Next p2 Next p1 ElseIf Right(WADDir()\Name,6)="_START" If Left(WADDir()\Name,1)="F" WADDir()\Flat=0 FlatFlag=1 ElseIf Left(WADDir()\Name,1)="S" WADDir()\Flat=0 FlatFlag=2 EndIf ElseIf Right(WADDir()\Name,4)="_END" WADDir()\Flat=0 FlatFlag=0 ElseIf WADDir()\Name="PNAMES" ;load a list of all texture names patches offset.l=0 *mem2=AllocateMemory(8) FileSeek(File,WADDir()\FilePos+offset) ReadData(File,*mem2,4) TPatches.l=PeekL(*mem2) offset+4 For P=1 To TPatches AddElement(PName()) FileSeek(File,WADDir()\FilePos+offset) ReadData(File,*mem2,8) PName()\LumpName=Trim(PeekS(*mem2,8)) offset+8 Next p FreeMemory(*mem2) ElseIf Left(WADDir()\Name,7)="TEXTURE" ;TEXTURE1 or TEXTURE2 offset.l=0 *mem2=AllocateMemory(26) FileSeek(File,WADDir()\FilePos+offset) ReadData(File,*mem2,4) TTexture.l=PeekL(*mem2) offset+4 For P=1 To TTexture AddElement(Texture()) FileSeek(File,WADDir()\FilePos+offset) ReadData(File,*mem2,4) Texture()\LumpCount=ListIndex(WADdir()) Texture()\FilePos=PeekL(*mem2)+WADDir()\FilePos ;and finish the data FileSeek(File,Texture()\FilePos) ReadData(File,*mem2,24) Texture()\Name=Trim(PeekS(*mem2,8)) Texture()\Width=PeekW(*mem2+12) Texture()\Height=PeekW(*mem2+14) Texture()\PatchCount=PeekW(*mem2+20) AddElement(Patch()) Texture()\FirstPatch=ListIndex(Patch()) POff.l=Texture()\FilePos+22 For TP=1 To Texture()\PatchCount FileSeek(File,POff) ReadData(File,*mem2,2) Patch()\OriginX=PeekW(*mem2) FileSeek(File,POff+2) ReadData(File,*mem2,2) Patch()\OriginY=PeekW(*mem2) FileSeek(File,POff+4) ReadData(File,*mem2,2) Patch()\Index=PeekW(*mem2) POff + 10 If TP=NHead Break EndIf Next h POff + 4 Next C StopDrawing() ;ResizeImage(GraphicCount,190,190) FreeMemory(*mem) Else ;this works for FLATS only which use a 256 color palet previously loaded FileSeek(File,WADDir()\FilePos) *mem=AllocateMemory(WADDir()\Size) ReadData(File,*mem,WADDir()\Size) GraphicCount+1 WADDir()\Graphic=GraphicCount ;assume image is square ;so we must determine the image size ;each byte is a pixel, we need the PlayPal() ;to determine color .... W.l=Sqr(WADDir()\Size) CreateImage(GraphicCount,W,W) WADDir()\width=w WADDir()\height=w StartDrawing(ImageOutput(GraphicCount)) Off.l=0 For y=0 To W-1 For x=0 To W-1 CP.l=PeekB(*mem+off)&$FF Plot(x,y,PlayPal(CP)) Off + 1 Next x Next y StopDrawing() ;ResizeImage(GraphicCount,190,190) FreeMemory(*mem) EndIf EndIf EndIf ;- reconcile the PName list to Directory ResetList(PName()) While NextElement(PName()) If WADDir()\Name=PName()\LumpName PName()\LumpCount=ListIndex(WADDir()) PName()\FilePos=WADDir()\FilePos PName()\Size=WADDir()\Size If WADDir()\Graphic PName()\Graphic=WADDir()\Graphic Else If WADDir()\Size FileSeek(File,WADDir()\FilePos) *mem=AllocateMemory(WADDir()\Size) ReadData(File,*mem,WADDir()\Size) ;extra data for tracking sprites and patches WADDir()\width=PeekW(*mem) WADDir()\height=PeekW(*mem+2) WADDir()\leftoff=PeekW(*mem+4) WADDir()\topoff=PeekW(*mem+6) POff.l=8 For C=0 To 7 WADDir()\column[C]=PeekL(*mem+POff) POff+4 Next C ;skip all other column headers .... POff=8 GraphicCount+1 WADDir()\Graphic=GraphicCount CreateImage(GraphicCount,WADDir()\width,WADDir()\height) StartDrawing(ImageOutput(GraphicCount)) For C=0 To WADDir()\width-1 CHead.l=PeekL(*mem+Poff) Marker1.l=PeekB(*mem+CHead)&$FF Marker2.l=PeekB(*mem+CHead+1)&$FF Marker3.l=PeekW(*mem+CHead) CHead+2 If C=NHead Break ElseIf CHead<0 Debug "CHead<0 for PNAme WADDir() "+Str(ListIndex(WADDir())) Debug "Column "+Str(c) Break 2 EndIf Pal=PeekB(*mem+CHead)&$FF Plot(C,H,PlayPal(Pal)) CHead + 1 Next h POff + 4 Next C StopDrawing() ;ResizeImage(GraphicCount,190,190) PName()\Graphic=WADDir()\Graphic FreeMemory(*mem) EndIf EndIf Break EndIf Wend SetGadgetState(#ProgressBar,ListIndex(WADDir())) Repeat event=WindowEvent() If event=#PB_Event_CloseWindow If EventWindow()=#Window_Prog End EndIf EndIf Until event=0 Wend CloseFile(File) ;- reconcile DoomED vs Sprite SetWindowTitle(#Window_Prog,"Preparing Sprites") SetGadgetState(#ProgressBar,0) SetGadgetAttribute(#ProgressBar,#PB_ProgressBar_Maximum,CountList(DoomSprite())) ResetList(DoomSprite()) While NextElement(DoomSprite()) ResetList(WADDir()) While NextElement(WADDir()) DName.s=UCase(Left(WADDir()\Name,4)) If DoomSprite()\Name=DName DoomSprite()\Graphic=WADDir()\Graphic Break EndIf Wend SetGadgetState(#ProgressBar,ListIndex(DoomSprite())) Repeat event=WindowEvent() If event=#PB_Event_CloseWindow If EventWindow()=#Window_Prog End EndIf EndIf Until event=0 Wend ;- build textures from patch list ..... SetWindowTitle(#Window_Prog,"Building Textures") SetGadgetState(#ProgressBar,0) SetGadgetAttribute(#ProgressBar,#PB_ProgressBar_Maximum,CountList(Texture())) ResetList(Texture()) While NextElement(Texture()) GraphicCount + 1 CreateImage(GraphicCount,Texture()\Width,Texture()\Height) Texture()\Graphic=GraphicCount StartDrawing(ImageOutput(GraphicCount)) SelectElement(Patch(),Texture()\FirstPatch) ;Debug "Making Texture "+Texture()\Name ;Debug "Width,Height" +Str(Texture()\width)+","+Str(Texture()\Height) ;Debug "PatchCount "+Str(Texture()\PatchCount) For P=1 To Texture()\PatchCount If Patch()\Graphic=0 SelectElement(PName(),Patch()\Index) Patch()\Graphic=PName()\Graphic SelectElement(WADDir(),PName()\LumpCount) Patch()\Width=WADDir()\Width Patch()\Height=WADDir()\Height EndIf If Patch()\Graphic DrawImage(ImageID(Patch()\Graphic),Patch()\OriginX,Patch()\OriginY,Patch()\Width,Patch()\Height) ;SelectElement(PName(),Patch()\Index) ;Debug "Using Patch "+PName()\LumpName ;Debug "Origin X,Y"+Str(Patch()\OriginX)+","+Str(Patch()\OriginY) ;SelectElement(WADDir(),PName()\LumpCount) ;Debug "Patch Size "+Str(WADDir()\Width)+","+Str(WADDir()\Height) Else ;Debug "Patch Not Found" ;Debug "Index = "+Str(Patch()\Index) ;Debug "PName = "+PName()\LumpName ;Debug "Texture ID,Name "+Str(ListIndex(Texture()))+","+Texture()\Name EndIf ;CallDebugger NextElement(Patch()) Next P StopDrawing() ;ResizeImage(GraphicCount,190,190) SetGadgetState(#ProgressBar,ListIndex(Texture())) Repeat event=WindowEvent() If event=#PB_Event_CloseWindow If EventWindow()=#Window_Prog End EndIf EndIf Until event=0 Wend CloseWindow(#Window_Prog) EndIf ProcedureReturn reply EndProcedure Procedure LoadMap(index.l) SelectElement(WADDir(),index) File.l=ReadFile(#PB_Any,WADInfo\WADName) If File NextElement(WADDir()) ;verify this is things If WADDir()\Name="THINGS" ;- load all things If WADInfo\WADStyle *mem=AllocateMemory(20) DS.l=20 Else *mem=AllocateMemory(10) DS=10 EndIf Offset.l=0 ClearList(MapThing()) ClearList(LineDef()) ClearList(SideDef()) ClearList(Vertex()) ClearList(Sector()) Repeat AddElement(MapThing()) FileSeek(File,WADDir()\FilePos+Offset) ReadData(File,*mem,DS) If DS>10 MapThing()\ThingID=PeekW(*mem) MapThing()\x=PeekW(*mem+2) MapThing()\y=PeekW(*mem+4) MapThing()\h=PeekW(*mem+6) MapThing()\angle=PeekW(*mem+8) MapThing()\DoomED=PeekW(*mem+10) MapThing()\Flags=PeekW(*mem+12) MapThing()\action=PeekB(*mem+14)&$FF MapThing()\Arg1=PeekB(*mem+15)&$FF MapThing()\Arg2=PeekB(*mem+16)&$FF MapThing()\Arg3=PeekB(*mem+17)&$FF MapThing()\Arg4=PeekB(*mem+18)&$FF MapThing()\Arg5=PeekB(*mem+19)&$FF Else MapThing()\x=PeekW(*mem) MapThing()\y=PeekW(*mem+2) MapThing()\angle=PeekW(*mem+4) MapThing()\DoomED=PeekW(*mem+6) MapThing()\Flags=PeekW(*mem+8) EndIf ;DName.s=UCase(Left(WADDir()\Name,4)) ResetList(DoomSprite()) While NextElement(DoomSprite()) If DoomSprite()\DoomED=MapThing()\DoomED MapThing()\Graphic=DoomSprite()\Graphic Break EndIf Wend offset + DS Until Offset>WADDir()\Size NextElement(WADDir()) FreeMemory(*mem) EndIf If WADDir()\Name="LINEDEFS" ;- Load LineDefs If WADInfo\WADStyle *mem=AllocateMemory(16) DS.l=16 Else *mem=AllocateMemory(14) DS=14 EndIf Offset.l=0 Repeat AddElement(LineDef()) FileSeek(File,WADDir()\FilePos+Offset) ReadData(File,*mem,DS) If DS>14 ;hexen LineDef()\VStart=PeekW(*mem) LineDef()\VEnd=PeekW(*mem+2) LineDef()\Flags=PeekW(*mem+4) LineDef()\Special=PeekB(*mem+6)&$FF LineDef()\Arg1=PeekB(*mem+7)&$FF LineDef()\Arg2=PeekB(*mem+8)&$FF LineDef()\Arg3=PeekB(*mem+9)&$FF LineDef()\Arg4=PeekB(*mem+10)&$FF LineDef()\Arg5=PeekB(*mem+11)&$FF LineDef()\RSideDef=PeekW(*mem+12) LineDef()\LSideDef=PeekW(*mem+14) Else ;classic doom LineDef()\VStart=PeekW(*mem) LineDef()\VEnd=PeekW(*mem+2) LineDef()\Flags=PeekW(*mem+4) LineDef()\Special=PeekW(*mem+6) LineDef()\Sector=PeekW(*mem+8) LineDef()\RSideDef=PeekW(*mem+10) LineDef()\LSideDef=PeekW(*mem+12) EndIf ;Flags .... ;0 0x0001 blocks players And monsters ;1 0x0002 blocks monsters ;2 0x0004 two sided ;3 0x0008 upper texture is unpegged ;4 0x0010 lower texture is unpegged ;5 0x0020 secret (shows As one-sided on automap), ;And monsters cannot open If it is a door (type 1) ;6 0x0040 blocks sound ;7 0x0080 never shows on automap ;8 0x0100 always shows on automap ;9 0x0200 can be activated more than once [hexen only] ;Hexen combines flags 10,11,12 (0x0400 + 0x0800 + 0x1000) ;10 0x0400 activated when used by player [hexen] ;11 0x0800 activated when crossed by monster [hexen] ;(10+11) 0x0C00 activated when hit by projectile [hexen] ;(10+12) 0x1400 activated crossed by projectile [hexen] ;(11+12) 0x1800 activated when used by player (With pass through) [hexen] ;13 0x2000 line can be activated by players And monsters [hexen] ;14 0x4000 [Hexen] ?? ;15 0x8000 blocks everything (includes gunshots & missiles) Offset + DS Until Offset>WADDir()\Size NextElement(WADDir()) FreeMemory(*mem) EndIf If WADDir()\Name="SIDEDEFS" DS=30 ;for Doom or Hexen, same size *mem=AllocateMemory(30) Offset.l=0 ;- Load SideDefs Repeat AddElement(SideDef()) FileSeek(File,WADDir()\FilePos+Offset) ReadData(File,*mem,DS) SideDef()\xoffset=PeekW(*mem) SideDef()\yoffset=PeekW(*mem+2) ;texture names SideDef()\UTName=PeekS(*mem+4,8) SideDef()\LTName=PeekS(*mem+12,8) SideDef()\MTname=PeekS(*mem+20,8) SideDef()\Sector=PeekW(*mem+28) Offset + DS Until Offset>WADDir()\Size NextElement(WADDir()) FreeMemory(*mem) EndIf If WADDir()\Name="VERTEXES" ;- load vertexes DS=4 ;for Doom or Hexen, same size *mem=AllocateMemory(4) Offset.l=0 Repeat AddElement(Vertex()) FileSeek(File,WADDir()\FilePos+Offset) ReadData(File,*mem,DS) Vertex()\VX=PeekW(*mem) Vertex()\VY=PeekW(*mem+2) Offset + DS Until Offset>WADDir()\Size ;skip SEGS,SSECTORS,NODES ;as these are "rendering optimizers" ;and not really usefull here NextElement(WADDir()) NextElement(WADDir()) NextElement(WADDir()) NextElement(WADDir()) FreeMemory(*mem) EndIf If WADDir()\Name="SECTORS" ;- load sectors DS=26 ;for Doom or Hexen, same size *mem=AllocateMemory(DS) Offset.l=0 Repeat AddElement(Sector()) FileSeek(File,WADDir()\FilePos+Offset) ReadData(File,*mem,DS) Sector()\FloorH=PeekW(*mem) Sector()\CeilingH=PeekW(*mem+2) Sector()\FName=PeekS(*mem+4,8) Sector()\CName=PeekS(*mem+12,8) Sector()\Light=PeekW(*mem+20) Sector()\LType=PeekW(*mem+22) Sector()\Tag=PeekW(*mem+24) Offset + DS Until Offset>WADDir()\Size FreeMemory(*mem) EndIf CloseFile(File) SelectElement(WADDir(),index) EndIf EndProcedure Procedure OverViewMap(Index.l) LoadMap(Index) SelectElement(WADDir(),index) ;each LineDef has 2 vertexes (start and end) ; and has 2 sides .... SideDefs ;each SideDef has 3 wall textures (upper,middle,lower) ; and specifies the facing sector ;each Sector has 2 textures (floor and Ceiling) ;lets start with a basic windowed directx screen ;modify LineDefs to add vertex data to LineDef TopY.l=0 LeftX.l=0 Scale.f=0.2 BotY.l=TopY+400 RightX.l=LeftX+400 ResetList(LineDef()) While NextElement(LineDef()) If SelectElement(Vertex(),LineDef()\VStart) LineDef()\PVStart\VX=Vertex()\VX LineDef()\PVStart\VY=Vertex()\VY If SelectElement(Vertex(),LineDef()\VEnd) LineDef()\PVEnd\VX=Vertex()\VX LineDef()\PVEnd\VY=Vertex()\VY Else LineDef()\PVEnd\VX=LineDef()\PVStart\VX LineDef()\PVEnd\VY=LineDef()\PVStart\VY EndIf Else If SelectElement(Vertex(),LineDef()\VEnd) LineDef()\PVEnd\VX=Vertex()\VX LineDef()\PVEnd\VY=Vertex()\VY LineDef()\PVStart\VX=Vertex()\VX LineDef()\PVStart\VY=Vertex()\VY EndIf EndIf ;check if vertex is visible If LineDef()\PVStart\VX*ScaleRightX RightX=LineDef()\PVStart\VX*Scale LeftX=RightX-400 EndIf If LineDef()\PVStart\VY*ScaleBotY BotY=LineDef()\PVStart\VY*Scale TopY=BotY-400 EndIf Wend FN$=WADDir()\Name If WADInfo\WADStyle FN$=FN$+" [HEXEN] OverView" Else FN$=FN$+" [DOOM] OverView" EndIf wflags.l=#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_SizeGadget|#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered OpenWindow(#Window_OverView,0,0,400,400,FN$,wflags) CreateMenu(#ViewMenu,WindowID(#Window_Overview)) MenuTitle("Map") MenuItem(#Reset,"Reset View"+Chr(9)+"Ctrl R") MenuItem(#Exit,"Exit Viewer") MenuItem(#Quit,"Quit Tool") MenuTitle("Zoom") MenuItem(#ZoomIN,"In"+Chr(9)+"Ctrl X") MenuItem(#ZoomOut,"Out"+Chr(9)+"Ctrl Z") MenuItem(#ZoomLeft,"Left"+Chr(9)+"Ctrl A") MenuItem(#ZoomRight,"Right"+Chr(9)+"Ctrl D") MenuItem(#ZoomUP,"Up"+Chr(9)+"Ctrl W") MenuItem(#ZoomDown,"Down"+Chr(9)+"Ctrl S") MenuTitle("Draw") MenuItem(#Draw_ID,"Show DoomED") MenuItem(#Draw_Sprite,"Use Icons") MenuItem(#Draw_Off,"No Things") : SetMenuItemState(#ViewMenu,#Draw_Off,#True) AddKeyboardShortcut(#Window_OverView,#PB_Shortcut_R | #PB_Shortcut_Control,#Reset) AddKeyboardShortcut(#Window_OverView,#PB_Shortcut_Z | #PB_Shortcut_Control,#ZoomOut) AddKeyboardShortcut(#Window_OverView,#PB_Shortcut_X | #PB_Shortcut_Control,#ZoomIN) AddKeyboardShortcut(#Window_OverView,#PB_Shortcut_A | #PB_Shortcut_Control,#ZoomLeft) AddKeyboardShortcut(#Window_OverView,#PB_Shortcut_S | #PB_Shortcut_Control,#ZoomDown) AddKeyboardShortcut(#Window_OverView,#PB_Shortcut_D | #PB_Shortcut_Control,#ZoomRight) AddKeyboardShortcut(#Window_OverView,#PB_Shortcut_W | #PB_Shortcut_Control,#ZoomUP) OpenWindowedScreen(WindowID(#Window_OverView),0,0,400,400,0,0,0) WALL.l=RGB(200,0,0) DOOR.l=RGB(255,255,0) Secret.l=RGB(0,255,0) Special.l=RGB(0,0,255) Nothing.l=RGB(50,50,50) ReScreen.l=0 orgx.l=leftx orgy.l=topy Repeat event.l=WindowEvent() If event=#PB_Event_Menu ClearScreen(0) Select EventMenu() Case #Reset scale=0.2 LeftX=OrgX RightX=LeftX+WindowWidth(#Window_OverView) TopY=OrgY BotY=TopY+WindowHeight(#Window_OverView) Case #Exit Break Case #Quit End Case #ZoomIN Debug "ZoomIN" Debug "LeftX "+Str(LeftX) Debug "RightX "+Str(RightX) cx.l=(LeftX+RightX)/2 rcx.l=cx/scale Debug "CX "+Str(CX) Debug "Real CX "+Str(rcx) cy.l=(TopY+BotY)/2 rcy.l=cy/scale Debug "Real CY2 "+Str(rcy) scale=scale*2.0 Debug "Scale New "+StrF(Scale,2) ncx.l=cx/scale ncy.l=cy/scale rcxe.l=ncx-rcx rcye.l=ncy-rcy Debug "Errors rcxe,rcye "+Str(rcxe)+","+Str(rcye) leftX-scale*rcxe RightX=LeftX+WindowWidth(#Window_OverView) Topy-scale*rcye BotY=TopY+WindowHeight(#Window_OverView) Debug "LeftX "+Str(LeftX) Debug "RightX "+Str(RightX) cx.l=(LeftX+RightX)/2 Debug "CX2 "+Str(CX) Debug "Real CX2 "+Str(CX/Scale) cy.l=(TopY+BotY)/2 Debug "Real CY2 "+Str(CY/Scale) Case #ZoomOut Debug "ZoomOut" Debug "LeftX "+Str(LeftX) Debug "RightX "+Str(RightX) cx.l=(LeftX+RightX)/2 rcx.l=cx/scale Debug "CX "+Str(CX) Debug "Real CX "+Str(rcx) cy.l=(TopY+BotY)/2 rcy.l=cy/scale Debug "Real CY2 "+Str(rcy) scale=scale/2.0 Debug "Scale New "+StrF(Scale,2) ncx.l=cx/scale ncy.l=cy/scale rcxe.l=ncx-rcx rcye.l=ncy-rcy Debug "Errors rcxe,rcye "+Str(rcxe)+","+Str(rcye) leftX-scale*rcxe RightX=LeftX+WindowWidth(#Window_OverView) Topy-scale*rcye BotY=TopY+WindowHeight(#Window_OverView) Debug "LeftX "+Str(LeftX) Debug "RightX "+Str(RightX) cx.l=(LeftX+RightX)/2 Debug "CX2 "+Str(CX) Debug "Real CX2 "+Str(CX/Scale) cy.l=(TopY+BotY)/2 Debug "Real CY2 "+Str(CY/Scale) Case #ZoomLeft LeftX=LeftX-100*Scale RightX=RightX-100*scale Debug "LeftX "+Str(LeftX) Case #ZoomRight LeftX=LeftX+100*Scale RightX=RightX+100*scale Debug "LeftX "+Str(LeftX) Case #ZoomUP TopY=TopY+100*Scale BotY=BotY+100*Scale Case #ZoomDown TopY=TopY-100*Scale BotY=BotY-100*Scale Case #Draw_ID SetMenuItemState(#ViewMenu,#Draw_ID,#True) SetMenuItemState(#ViewMenu,#Draw_Off,#False) SetMenuItemState(#ViewMenu,#Draw_Sprite,#False) Case #Draw_Sprite SetMenuItemState(#ViewMenu,#Draw_Sprite,#True) SetMenuItemState(#ViewMenu,#Draw_Off,#False) SetMenuItemState(#ViewMenu,#Draw_ID,#False) Case #Draw_Off SetMenuItemState(#ViewMenu,#Draw_Off,#True) SetMenuItemState(#ViewMenu,#Draw_ID,#False) SetMenuItemState(#ViewMenu,#Draw_Sprite,#False) EndSelect ElseIf Event=#PB_Event_SizeWindow ReScreen=GetTickCount_()+1000 EndIf If ReScreen If ReScreen=0 msg$=GetGadgetItemText(#ListIcon_0,GS) lumpstart.l=Val(GetGadgetItemText(#ListIcon_0,GS,1)) Break EndIf ElseIf GadgetID= #Button_4 GS.l=GetGadgetState(#ListIcon_0) If GS>=0 msg$=GetGadgetItemText(#ListIcon_0,GS) lumpstart.l=Val(GetGadgetItemText(#ListIcon_0,GS,1)) OverView.l=1 Break EndIf EndIf EndIf Until Event = #PB_Event_CloseWindow ; End of the event loop CloseWindow(#Window_List) If lumpstart LoadMap(lumpstart) If OverView OverViewMap(LumpStart) OverView=0 Else MapDetails() EndIf EndIf Until lumpstart=0 EndProcedure Procedure TestWAD() Repeat P$=GetPathPart(ProgramFilename())+"*.wad" FN$=OpenFileRequester("Select a WAD file to scan",P$,"wad files(*.wad,iwad)|*.wad;*.iwad|All Files (*.*)|*.*",0) If FN$ LoadWAD(FN$) ListMaps() EndIf Until FN$="" EndProcedure Procedure Initialize() If InitSprite()=0 ProcedureReturn #False EndIf If InitSprite3D()=0 ProcedureReturn #False EndIf ProcedureReturn #True EndProcedure Initialize() TestWAD()